/*        This file is part of P5ovray.
        
        P5ovray is free software: you can redistribute it and/or modify
        it under the terms of the GNU Lesser General Public License as 
        published by the Free Software Foundation, either version 3 of 
        the License, or (at your option) any later version.
        
        P5ovray is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU Lesser General Public License for more details.
        
        You should have received a copy of the GNU Lesser General Public
        License along with P5ovray.  If not, see <http://www.gnu.org/licenses/>.
*/

package zombie.povray;

import processing.core.PMatrix3D;
import java.util.ArrayList;

public class P5ovObject {

	public String name;
	
	//	ArrayLists to hold attributes and objects that are held in the current object.
	ArrayList<P5ovVec3f> vec3fs;
	ArrayList<P5ovObject> objectList;
	
	P5ovVec3f pos3f;
	P5ovVec3 pos3;
	String locString = new String();
	boolean hasLocString = false;
	
	boolean hasMatrix = false;
	PMatrix3D matrix;
	
	ArrayList<String> stringList = new ArrayList<String>();
	
	int tabLevel = 0;
	
	public static enum P5ovObjPos{
		NOPOSITION,
		POSITION3,
		POSITION3F
	};
	
	public P5ovObjPos hasPosition;
	float hasSize;
	
	public P5ovObject ( String _name )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.NOPOSITION;
		pos3f = new P5ovVec3f();
		pos3 = new P5ovVec3();
	}
	
	public P5ovObject ( String _name, String _locString )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.NOPOSITION;
		pos3f = new P5ovVec3f();
		pos3 = new P5ovVec3();
		locString = _locString;
		hasLocString = true;
	}
	
	public P5ovObject ( String _name, float x, float y, float z, PMatrix3D _matrix, boolean hasLocName)
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3F;
		hasSize = -1;
		matrix = new PMatrix3D(_matrix);
		hasMatrix = true;
		if (hasLocName)
			pos3f = new P5ovVec3f( x, y, z, "location " );
		else
			pos3f = new P5ovVec3f( x, y, z);
		pos3 = new P5ovVec3();
	}
	
	public P5ovObject ( String _name, float x, float y, float z, PMatrix3D _matrix, float size)
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3F;
		hasSize = size;
		matrix = new PMatrix3D(_matrix);
		hasMatrix = true;
		pos3f = new P5ovVec3f( x, y, z);
		
		pos3 = new P5ovVec3();
	}
	
	public P5ovObject ( String _name, PMatrix3D _matrix, float _size )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3;
		hasSize = _size;
		matrix = new PMatrix3D(_matrix);
		hasMatrix = true;
		pos3f = new P5ovVec3f( 0, 0, 0 );
		pos3 = new P5ovVec3();
	}
	
	public P5ovObject ( String _name, PMatrix3D _matrix )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3;
		hasSize = -1;
		matrix = new PMatrix3D(_matrix);
		hasMatrix = true;
		pos3f = new P5ovVec3f( 0, 0, 0 );
		pos3 = new P5ovVec3();
	}
	
	
	public P5ovObject ( String _name, float x, float y, float z )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3F;
		hasSize = -1;
		pos3f = new P5ovVec3f( x, y, z );
		pos3 = new P5ovVec3();
	}
	
	public P5ovObject ( String _name, float x, float y, float z, float _size )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3F;
		hasSize = _size;
		pos3f = new P5ovVec3f( x, y, z );
		pos3 = new P5ovVec3();
	}
	
	public P5ovObject ( String _name, int x, int y, int z )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3;
		hasSize = -1;
		pos3f = new P5ovVec3f();
		pos3 = new P5ovVec3( x, y, z );
	}
	
	public P5ovObject ( String _name, int x, int y, int z, float _size )
	{
		name = _name;
		vec3fs = new ArrayList<P5ovVec3f>();
		objectList = new ArrayList<P5ovObject>();
		hasPosition = P5ovObjPos.POSITION3;
		hasSize = _size;
		pos3f = new P5ovVec3f();
		pos3 = new P5ovVec3( x, y, z );
	}
	
	public void addObject ( P5ovObject _object )
	{
		_object.tabLevel = tabLevel + 1;
		objectList.add(_object);
	}
	
	public void addString ( String _objString )
	{
		stringList.add(_objString);
	}
	
	public void addVec3f (double x, double y, double z)
	{
		vec3fs.add(new P5ovVec3f(x,y,z));
	}
	
	public void addVec3f (double x, double y, double z, String fName)
	{
		vec3fs.add(new P5ovVec3f(x,y,z, fName));
	}
	
	public void addVec3f (double x, double y, double z, String fName, String fTrailing)
	{
		vec3fs.add(new P5ovVec3f(x,y,z, fName, fTrailing));
	}
	
	/*public void addVec3 (int x, int y, int z)
	{
		vec3fs.add(new P5ovVec3(x,y,z));
	}
	
	public void addVec3 (int x, int y, int z, String fName)
	{
		vec3fs.add(new P5ovVec3(x,y,z, fName));
	}
	
	public void addVec3 (int x, int y, int z, String fName, String fTrailing)
	{
		vec3fs.add(new P5ovVec3(x,y,z, fName, fTrailing));
	}*/
	
	private String getTabs()
	{
		String tabStr = new String();
		
		for(int i = 0; i < this.tabLevel +1; i++){
			tabStr += "\t";
		}
		
		return tabStr;
	}
	
	
	private String getTabsEnd()
	{
		String tabStr = new String();
		
		for(int i = 0; i < this.tabLevel; i++){
			tabStr += "\t";
		}
		
		return tabStr;
	}
	
	public String getString()
	{
		String str = new String();
		
		str += getTabsEnd() + name + " {\n";
		
		switch (hasPosition){
		
		case POSITION3:
			str += getTabs() + pos3.getString();
			if (hasSize > 0)
				str += ", " + hasSize + "\n";
			else
				str += "\n";
			break;
			
		case POSITION3F:
			str += getTabs() + pos3f.getString();
			if (hasSize > 0)
				str += ", " + hasSize + "\n";
			else
				str += "\n";
			break;
		}
		
		if (hasLocString){
			str += locString + "\n";
		}
		
		if (hasMatrix){
			
			str += getTabs() + "matrix < ";
			float[] matrixArray = new float[16];
			matrix.get(matrixArray);
			
			for (int i = 0; i < 16; i++){
				if (i != 3 && i != 7 && i != 11 && i != 15)
				{	
					str += matrixArray[i];
					if (i < 14)
						str += ", ";
				}
			}
			str += " >\n\n";
			
		}
		
		for(int i = 0; i < vec3fs.size() ; i++){
			P5ovVec3f _pos = vec3fs.get(i);
			str += getTabs() + _pos.getString() + "\n";
		}
		
		for(int i = 0; i < objectList.size() ; i++){
			P5ovObject _obj = objectList.get(i);
			str += _obj.getString() + "\n";
		}
		
		for(int i = 0; i < stringList.size(); i++){
			str += getTabs() + stringList.get(i) + "\n";
		}
		
		str += getTabsEnd() + "}\n";
		
		return str;
	}
	
	
}

class P5ovVec3f
{
	double x;
	double y;
	double z;
	String name;
	boolean hasName;
	String trailing;
	boolean hasTrailing;
	
	public P5ovVec3f()
	{
		x = 0.0;
		y = 0.0;
		z = 0.0;
		hasName = false;
		hasTrailing = false;
	}
	
	public P5ovVec3f( double _x, double _y, double _z )
	{
		x = _x;
		y = _y;
		z = _z;
		hasName = false;
		hasTrailing = false;
	}
	
	public P5ovVec3f( double _x, double _y, double _z, String _name )
	{
		x = _x;
		y = _y;
		z = _z;
		name = _name;
		hasName = true;
		hasTrailing = false;
	}
	
	public P5ovVec3f( double _x, double _y, double _z, String _name, String _trailing )
	{
		x = _x;
		y = _y;
		z = _z;
		name = _name;
		hasName = true;
		trailing = _trailing;
		hasTrailing = true;
	}
	
	public String getString()
	{
		String str;
		str = new String();
		
		if (hasName)
			str += name + " ";
		
		str += "<" + x + ", " + y + ", " + z + " >";
		
		if (hasTrailing)
			str += " " + trailing;
		
		return str;
	}
}

class P5ovVec3
{
	int x;
	int y;
	int z;
	String name;
	boolean hasName;
	String trailing;
	boolean hasTrailing;
	
	public P5ovVec3()
	{
		x = 0;
		y = 0;
		z = 0;
		hasName = false;
		hasTrailing = false;
	}
	
	public P5ovVec3( int _x, int _y, int _z )
	{
		x = _x;
		y = _y;
		z = _z;
		hasName = false;
		hasTrailing = false;
	}
	
	public P5ovVec3( int _x, int _y, int _z, String _name )
	{
		x = _x;
		y = _y;
		z = _z;
		name = _name;
		hasName = true;
		hasTrailing = false;
	}
	
	public P5ovVec3( int _x, int _y, int _z, String _name, String _trailing )
	{
		x = _x;
		y = _y;
		z = _z;
		name = _name;
		hasName = true;
		trailing = _trailing;
		hasTrailing = true;
	}
	
	public String getString()
	{
		String str;
		str = new String();
		
		if (hasName)
			str += name + " ";
		
		str += "<" + x + ", " + y + ", " + z + " >";
		
		if (hasTrailing)
			str += " " + trailing;
		
		return str;
	}
}

class P5ovAttribute
{
	String name;
	String text;
	
	public P5ovAttribute ( String _name, String _text )
	{
		name = _name;
		text = _text;
	}
	
}
